<?php
/**
 * crcl/base
 *
 * Copyright 2013 CRCL - André Sabosch - info@crcl.de
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

namespace crcl\base\mvc;

interface IFrontcontroller
{
  /**
   * Constructor. Creates resolver object
   */
  public function __construct();

  /**
   * Sets request object
   *
   * @param \crcl\base\mvc\request\IConcrete $oRequest
   */
  public function setRequest(\crcl\base\mvc\request\IConcrete $oRequest);

  //public function getRequest();

  /**
   * Sets router object and loads configuration
   *
   * @param \crcl\base\mvc\router\IConcrete $oRouter
   */
  public function setRouter(\crcl\base\mvc\router\IConcrete $oRouter);

//  public function getRouter();

//  public function setMapper(\base\mvc\mapper\IConcrete $oMapper);
//  public function getMapper();

  /**
   * Sets response object
   *
   * @param \crcl\base\mvc\response\IConcrete $oResponse
   */
  public function setResponse(\crcl\base\mvc\response\IConcrete $oResponse);

//  public function getResponse();

  /**
   * Sets view object
   *
   * @param \crcl\base\mvc\view\IConcrete $oView
   */
//  public function setView(\crcl\base\mvc\view\IConcrete $oView);

  /**
   * Run application - dispatching queue
   */
  public function run();
}

class Frontcontroller implements IFrontcontroller
{
  const CONFIG_DOMAIN = 'mvc';
  const CONFIG_KEY_SCHEME = 'scheme';

  public function __construct()
  {
    $this->oResolver = new \crcl\base\mvc\Resolver();
  }

  public function setRequest(\crcl\base\mvc\request\IConcrete $oRequest)
  {
    $this->oRequest = $oRequest;
  }
/*
  public function getRequest()
  {
    if (\is_null($this->_oRequest))
    {
      throw new Exception('No request object available.');
    }
    return $this->_oRequest;
  }
*/
  public function setRouter(\crcl\base\mvc\router\IConcrete $oRouter)
  {
    try
    {
      $aScheme = \crcl\base\Config::reader()
        ->setDefault(\FALSE)
        ->get(self::CONFIG_DOMAIN, self::CONFIG_KEY_SCHEME);
    }
    catch (\Exception $e)
    {
      //in test mvc there is a config file....
      //todo testing with second mvc?
      //@codeCoverageIgnoreStart
      $aScheme = \FALSE;
      //@codeCoverageIgnoreEnd
    }
    if ($aScheme)
    {
      $oRouter->setScheme($aScheme);
    }
    $this->oRouter = $oRouter;
  }
/*
  public function getRouter()
  {
    if (\is_null($this->_oRouter))
    {
      throw new Exception('No router object available.');
    }
    return $this->_oRouter;
  }

  public function setMapper(\base\mvc\mapper\IConcrete $oMapper)
  {
    $this->_oMapper = $oMapper;
  }

  public function getMapper()
  {
    if (\is_null($this->_oMapper))
    {
      throw new Exception('No mapper object available.');
    }
    return $this->_oMapper;
  }
*/
  public function setResponse(\crcl\base\mvc\response\IConcrete $oResponse)
  {
    $this->oResponse = $oResponse;
  }
/*
  public function getResponse()
  {
    if (\is_null($this->_oResponse))
    {
      throw new Exception('No response object available.');
    }
    return $this->_oResponse;
  }
*/


  public function run()
  {
    $this->oRouter->identifyProperties($this->oRequest);

    $oCommand = Command::fromRouter($this->oRouter);

    $oCommand = $this->oResolver->execute($oCommand);

    $oView = View::getInstanceFromCommand($oCommand)->execute();

    $this->oResponse->flush($oView);

//    $this->dispatch($oCommand);


  //  $oCommandChain = $this->_getCommandChain($oCommand);
  //  $this->_dispatch($oCommandChain);
  }

  /** PRIVATE *************************************************************************************/

  private $oRequest  = \NULL;
  private $oRouter   = \NULL;
  private $oResolver = \NULL;
  private $oResponse = \NULL;

  /*

  private $_oMapper   = \NULL;


  private function _getCommand()
  {
    //$oRequest = $this->getRequest();
    $oRouter  = $this->getRouter();
    $oMapper  = $this->getMapper();

    $oCommand = $oRouter->toCommand();
    $oCommand = $oMapper->process($oCommand);
    return $oCommand;
  }

  private function _getCommandChain(ICommand $oCommand)
  {
    $oChain = new \base\mvc\CommandChain();
    $oChain->addCommand($oCommand);
    return $oChain;
  }

  private function _dispatch(ICommandChain $oChain)
  {
    $oCommand = $oChain->getNextCommand();
    do
    {
      $oResolver = \base\mvc\Resolver::factory($oCommand, $this->getRouter());

      $oCommand = $oResolver->execute($oCommand);

      if (!$oCommand->isDone())
      {
        $oChain->addCommand($oCommand);
      }
      try
      {
        $oCommand = $oChain->getNextCommand();
      }
      catch (Exception $e)
      {
        if ($e->getMessage() == Exception::ERROR_NOCOMMAND)
        {
          $oCommand->setLast();
        }
      }
    } while (!$oCommand->isLast());

    if (!is_null($oCommand->getTemplate()))
    {
      $oView = \base\mvc\View::factory($oCommand, $this->_oResponse);
      $oResponse = $oView->execute();

      //@Xtodo filter
      $oResponse->flush();
    }
  }
  */
}
